import tkinter as tk
import sqlite3
import json
import os
import logging

from tkinter import ttk, filedialog, messagebox
from PIL import Image, ImageTk
from pypinyin import pinyin
from pathlib import Path
from tkinter import Frame, Canvas, Scrollbar
from typing import Tuple
from common import \
    setup_logging,\
    resource_path,\
    create_synced_scroll_canvases, \
    create_innerframe_with_vsb, \
    show_frame, \
    detect_file_encoding





class App:
    def __init__(self,root:tk.Tk) -> None:
        """
        确保日志系统初始化
        读取./pic/目录下的所有图片文件
        初始化全局使用的属性
        初始化数据库和界面控件
        """
        if not logging.getLogger().handlers:
            setup_logging()

        with os.scandir(resource_path("./pic/")) as entries:
            self.pic_names = [os.path.splitext(entry.name)[0] for entry in entries if entry.is_file()]
            logging.info(f"./pic/下所有去掉后缀的文件名: {self.pic_names}")
            print(f"./pic/下所有去掉后缀的文件名: {self.pic_names}")

        self.root = root
        self.dbpath = resource_path("./asa.db")
        self.imported_files = {}        # {"filename":"path"}
        self.structure_count ={}        # {"structure_path":"count_num",...}
        self.base_structure_count = {}  # {"structure_full_name":"count_num",...}  structure_full_name = material_name + structure_name

        self.init_db()
        self.init_nav_frame()
        self.init_content_frame()
        self.init_frame1()
        
    def init_db(self) -> None:
        """
        建立数据库连接
        判断变体是否可变, 并写入数据库
        创建视图
        """
        self.conn = sqlite3.connect(self.dbpath)
        self.conn.row_factory = sqlite3.Row
        self.cursor = self.conn.cursor()
        sql = """
            
        """





        sql_statement = """
            DROP VIEW IF EXISTS total_view;
        """
        self.cursor.execute(sql_statement)
        self.conn.commit()
        sql_statement = """
            CREATE VIEW total_view AS
            SELECT 
                asa.structure_name,
                asa.variant_name,
                asa.structure_material,
                asa.structure_full_name,
                asa.s_num,
                asa.structure_path,
                need.Wood,need.Fiber,
                need.Thatch,need.Clay,
                need.Flint,
                need.Stone,
                need.Crystal,
                need.Cementing_Paste,
                need.Metal_Ingot,
                need.Polymer,
                need.Element,
                need.Element_Shard,
                need.Hide  
            FROM 
                asa 
            INNER JOIN 
                need 
            ON 
                asa.structure_full_name = need.structure_full_name;
        """
        self.cursor.execute(sql_statement)
        self.conn.commit()

    def init_nav_frame(self) -> None:
        """创建左侧功能栏"""
        self.nav_frame = tk.Frame(self.root, width=200, bg='lightgray')
        self.nav_frame.pack(side='left', fill='y')

        btn1 = tk.Button(self.nav_frame, text="建筑模板", command=lambda: show_frame(self.frame1))
        btn2 = tk.Button(self.nav_frame, text="辅助画板", command=lambda: show_frame(self.frame2))
        btn3 = tk.Button(self.nav_frame, text="辅助钓鱼", command=lambda: show_frame(self.frame3))
        btn4 = tk.Button(self.nav_frame, text="互动地图", command=lambda: show_frame(self.frame4))

        btn1.pack(pady=10, fill='x')
        btn2.pack(pady=10, fill='x')
        btn3.pack(pady=10, fill='x')
        btn4.pack(pady=10, fill='x')
        
    def init_content_frame(self)-> None:
        """创建右侧页面容器, 多个功能页面全部叠放, 默认显示第一个功能页面"""
        self.content_frame = tk.Frame(root)
        self.content_frame.pack(side='right', expand=True, fill='both')
        self.frame1 = tk.Frame(self.content_frame, bg="#FFFFFF")
        self.frame2 = tk.Frame(self.content_frame, bg="#155313")
        self.frame3 = tk.Frame(self.content_frame, bg="#8F4317")
        self.frame4 = tk.Frame(self.content_frame, bg="#18117C")
        for frame in (self.frame1, self.frame2, self.frame3, self.frame4):
            frame.place(relx=0, rely=0, relwidth=1, relheight=1)
        show_frame(self.frame1)

    def init_frame1(self) -> None:
        """创建第一个功能能页面上的所有控件"""
        # 在frame1放6个容器
        frame1_1 = tk.Frame(self.frame1, bg="#FFFFFF")
        frame1_2 = tk.Frame(self.frame1, bg="#FFFFFF")
        frame1_3 = tk.Frame(self.frame1, bg="#FFFFFF")
        frame1_4 = tk.Frame(self.frame1, bg="#FFFFFF")
        self.frame1_5 = tk.Frame(self.frame1, bg="#FFFFFF")
        frame1_6 = tk.Frame(self.frame1, bg="#FFFFFF")

        frame1_1.place(relx=0, rely=0, relwidth=1, relheight=0.05)
        frame1_2.place(relx=0, rely=0.05, relwidth=0.6, relheight=0.95)
        frame1_3.place(relx=0.6, rely=0.05, relwidth=0.4, relheight=0.6)
        frame1_4.place(relx=0.6, rely=0.65, relwidth=0.4, relheight=0.05)
        self.frame1_5.place(relx=0.6, rely=0.7, relwidth=0.4, relheight=0.25)
        frame1_6.place(relx=0.6, rely=0.95, relwidth=0.4, relheight=0.05)

            ## frame1_1放两个容器
        frame1_1_1 = tk.Frame(frame1_1, bg="#FFFFFF")
        frame1_1_2 = tk.Frame(frame1_1, bg="#FFFFFF")
        frame1_1_1.place(relx=0, rely=0, relwidth=0.6, relheight=1)
        frame1_1_2.place(relx=0.6, rely=0, relwidth=0.4, relheight=1)

                ### 在frame1_1_1放三个控件
                    #### 导入文件标签
        label1_1 = tk.Label(frame1_1_1, text="导入文件:", font=("Arial", 11))
        label1_1.place(relx=0, rely=0, relwidth=0.2, relheight=1)
                    #### 下拉框
        self.file_combobox = ttk.Combobox(frame1_1_1, state="readonly")
        self.file_combobox.place(relx=0.2, rely=0, relwidth=0.6, relheight=1)
        self.file_combobox.bind("<Button-1>",self.select_file)
                    #### 打开文件按钮
        self.open_btn = tk.Button(frame1_1_1, text="打开文件", font=("Arial", 11), command=self.open_file)
        self.open_btn.place(relx=0.825, rely=0, relwidth=0.15, relheight=1)


                ### 在frame1_1_2放2个控件
                    #### 模板名称标签
        template_name_label = tk.Label(frame1_1_2, text="模板名称:", font=("Arial", 11))
        template_name_label.place(relx=0, rely=0, relwidth=0.2, relheight=1)
                    #### 模板名称文本框
        self.template_name_text = tk.Text(frame1_1_2,font=("Arial", 11))
        self.template_name_text.place(relx=0.2, rely=0, relwidth=0.8, relheight=1)

            ## 在frame1_2放文本框和滚动条
                ### 然后创建滚动条
        y_scrollbar = tk.Scrollbar(frame1_2)
        y_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        x_scrollbar = tk.Scrollbar(frame1_2, orient=tk.HORIZONTAL)
        x_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
                ### 先创建文本框
        self.text_box = tk.Text(frame1_2, wrap="none", font=("Courier", 11))  # wrap="none"允许水平滚动
        self.text_box.pack(side=tk.LEFT, expand=True, fill=tk.BOTH)
                ### 配置关联
        self.text_box.config(yscrollcommand=y_scrollbar.set, 
                            xscrollcommand=x_scrollbar.set)
        y_scrollbar.config(command=self.text_box.yview)
        x_scrollbar.config(command=self.text_box.xview)
        
            ## 在 frame1_3放两个容器,再放置两个协同滚动的canvas
        w3 = 0.6
        self.frame1_3_1 = tk.Frame(frame1_3, bg="#FFFFFF")
        self.frame1_3_2 = tk.Frame(frame1_3, bg="#FFFFFF")
        self.frame1_3_1.place(relx=0, rely=0, relwidth=w3, relheight=1)
        self.frame1_3_2.place(relx=w3, rely=0, relwidth=1-w3, relheight=1)
        (self.inner_frame_1, self.inner_frame_2,self.vsb_1) = create_synced_scroll_canvases(self.frame1_3_1,self.frame1_3_2)

            ## 在 frame1_4放两个按钮
                ### save按钮
        save_btn = tk.Button(frame1_4, text="save",  font=("Arial", 11), command=self.save_to_template)
        save_btn.place(relx=0, rely=0, relwidth=w3, relheight=1)
                ### 复制按钮
        copy_btn = tk.Button(frame1_4, text="copy", command=self.copy_to_clipboard, font=("Arial", 11))
        copy_btn.place(relx=w3, rely=0, relwidth=1-w3, relheight=1)
        
            ## 在frame1_5 放置带滚动条的canvas
                ### 显示统计信息的frame
        w5 = 0.3
        self.frame1_5_1 = tk.Frame(self.frame1_5, bg="#FFFFFF")
        self.frame1_5_2 = tk.Frame(self.frame1_5, bg="#FFFFFF")
        self.frame1_5_3 = tk.Frame(self.frame1_5, bg="#FFFFFF")
        self.frame1_5_1.place(relx=0, rely=0, relwidth=w5, relheight=1)
        self.frame1_5_2.place(relx=w5, rely=0, relwidth=w5, relheight=1)
        self.frame1_5_3.place(relx=w5*2, rely=0, relwidth=1-w5*2, relheight=1)
                ### 展示资源数量的frame
        (self.inner_frame_3,self.vsb_3) = create_innerframe_with_vsb(self.frame1_5_3)

            ## 在frame1_6 放置label提示
        label1_6 = tk.Label(frame1_6, text="报错or计算错误, 请在 bilibili 私聊 DaringWoo", anchor='center', font=("Arial", 11))
        label1_6.place(relx=0, rely=0, relwidth=1, relheight=1)
    
    def select_file(self,event):
        """选择文件，加入下拉框"""
        drop_area_ratio = 0.94
        if event.x / event.widget.winfo_width() < drop_area_ratio:
            path = filedialog.askopenfilename()
            if path:
                name = path.split("/")[-1]
                if name not in self.imported_files:
                    self.imported_files[name] = path
                    self.file_combobox['values'] = list(self.imported_files.keys())
                self.file_combobox.set(name)
            return "break"  # 阻止下拉框展开

    def open_file(self):
        """
        初始化部分全局属性
        打开下拉框选中的文件
        self.structure -> list 存储json文件中的所有路径
        self.content -> str 存储读取的文件内容, 用于显示到文本框
        self.template_name -> str  存储模板名称
        """
        self.flag = 0 # 控制显示修改前
        self.resources = {i:0 for i in self.pic_names}
        for widget in self.frame1_5_2.winfo_children():
            widget.destroy()
        filename = self.file_combobox.get()
        if filename in self.imported_files.keys():
            path = self.imported_files[filename]
            ecd = detect_file_encoding(path)
            with open(path,'r',encoding=ecd) as f:
                self.content = f.read()
            try:
                self.jsondata = json.loads(self.content)
            except Exception as e:
                messagebox.showerror("解析失败", f"导入的文件不是建筑模板！\n{e}")
                return

        self.json_to_structure()
        self.show_text()
        self.creat_tmp_db()
        self.count_structure()
        self.calculate_base_structure()
        self.show_base_structure()
        self.show_structure_count_messages()
        self.calculate_resources()
        self.show_resources()

    def json_to_structure(self):
        """
        将self.jsondata 转化成 seld.structure
        """
        self.structure = []
        self.template_name=self.jsondata["name"]
        logging.info(f"本次解析的建筑模板名称: {self.template_name}")
        entries = self.jsondata["entries"]
        for i in range(len(entries)):
            self.structure.append(entries[i]["structure"])

    def show_text(self):
        """
        显示 self.content 和 self.template_name 
        """
        self.text_box.delete(1.0,tk.END)
        self.text_box.insert(tk.END,self.content)
        self.template_name_text.delete(1.0,tk.END)
        self.template_name_text.insert(tk.END,self.template_name)

    def creat_tmp_db(self):
        """
        创建 tmp_table
        self.structure 
        """
        sql_statement = """
            DROP TABLE IF EXISTS tmp_table ;
        """
        self.cursor.execute(sql_statement)
        placeholders = ",".join(["?"] * len(self.structure))  # 生成 "?,?,?"
        sql_statement = f"CREATE TEMP TABLE tmp_table AS SELECT * FROM asa WHERE structure_path IN ({placeholders});"
        self.cursor.execute(sql_statement,self.structure)
        sql_statement = f"ALTER TABLE tmp_table ADD COLUMN show_num TEXT;"
        self.cursor.execute(sql_statement)
        sql_statement = f"ALTER TABLE tmp_table ADD COLUMN changed_material TEXT;"
        self.cursor.execute(sql_statement)
        sql_statement = f"ALTER TABLE tmp_table ADD COLUMN changed_path TEXT;"
        self.cursor.execute(sql_statement)
        self.conn.commit()

    def count_structure(self):
        """
        self.structure_count -> dict 存储压缩后的建筑路径
        """
        self.structure_count = {}
        for item in self.structure:
            if item in self.structure_count:
                self.structure_count[item] += 1
            else:
                self.structure_count[item] = 1
        logging.info(f"json文件中建筑结构数量: {len(self.structure)}")
        logging.info(f"去重后的建筑结构数量: {len(self.structure_count)}")
        print(f"json文件中建筑结构数量: {len(self.structure)}")
        print(f"去重后的建筑结构数量: {len(self.structure_count)}")
        
    def calculate_base_structure(self):
        """
        根据压缩后的建筑结构self.structure_count计算基础建筑结构self.base_structure_count
        更新tmp_table.show_num, 记录去重后的建筑结构被压缩到第n行标签显示,用于修改材质后回溯
        """
        self.list_structure_show = []
        self.base_structure_count = {}
        for i,key in enumerate(self.structure_count.keys()):
            sql_statement_1 = """
                SELECT structure_full_name 
                FROM tmp_table 
                WHERE structure_path = ? ;
            """
            result = self.cursor.execute(sql_statement_1,(key,))
            result = result.fetchone()
            if result is None:
                logging.error(f"{key} - Missing data: asa.structure_path")
                messagebox.showerror("建筑结构路径不存在", f"tmp_table 中不存在:{key}")
                return
            structure_full_name = result["structure_full_name"]
            if structure_full_name in self.list_structure_show:
                index = self.list_structure_show.index(structure_full_name)
                self.base_structure_count[structure_full_name] += self.structure_count[key]
            else:
                self.list_structure_show.append(structure_full_name)
                index = self.list_structure_show.index(structure_full_name)
                self.base_structure_count[structure_full_name] = self.structure_count[key]
            sql_statement = f"UPDATE tmp_table SET show_num = {index} WHERE  structure_full_name = \"{structure_full_name}\""
            self.cursor.execute(sql_statement)
            self.conn.commit()
        logging.info(f"基础建结构数量: {len(self.base_structure_count)}")
        print(f"基础建结构数量: {len(self.base_structure_count)}")

    def show_base_structure(self):
        """
        展示基础建筑结构、数量和材质
        """
        for widget in self.inner_frame_1.winfo_children():
            widget.destroy()
        for widget in self.inner_frame_2.winfo_children():
            widget.destroy()
        if not self.base_structure_count:
            return
        
        label_height = 25
        padding = 5

        left_width = self.frame1_3_1.winfo_width() - self.vsb_1.winfo_width()
        right_width = self.frame1_3_2.winfo_width() - self.vsb_1.winfo_width()

        for i, (name, count) in enumerate(self.base_structure_count.items()):
            y = i * (label_height + padding)

            # 名称标签
            tk.Label(self.inner_frame_1, text=name, anchor="w",
                    bg="#91CF8F").place(x=0, y=y, width=left_width*0.79, height=label_height)
            
            # 材料选择下拉框
            combo = ttk.Combobox(self.inner_frame_2, state="readonly",
                    )
            combo.place(x=0, y=y, width=right_width, height=label_height)
            combo.bind("<MouseWheel>", lambda e: "break")
            
            # 根据结构全名获取基本结构体名称
            sql_statement_3 = "SELECT structure_name, structure_material   FROM need  WHERE structure_full_name =\""+name+"\";"
            result = self.cursor.execute(sql_statement_3).fetchone()

            # 根据结构体名称获取材质加入下拉框, 并设置下拉框当前值
            sql_statement_4 = "SELECT structure_material FROM need WHERE structure_name =\"" + result["structure_name"] + "\";"
            try:
                result2 = self.cursor.execute(sql_statement_4).fetchall()
                result3 = []
                for line in result2:
                    result3.append(line["structure_material"])
            except Exception:
                result3 = []
            # 按完整拼音排序
            def safe_pinyin(s: str) -> str:
                py = pinyin(s)
                if not py or not py[0]:  # 空字符串或无法转拼音
                    return s
                return ''.join(py[0])
            if len(result3) > 1:
                result3 = sorted(result3, key=safe_pinyin)
            combo['values'] = result3
            combo.set(result["structure_material"])
            

            # 数量标签（蓝色）
            tk.Label(self.inner_frame_1, text=str(count), anchor="w",
                    bg="#ADD8E6").place(x=left_width*0.8, y=y, width=left_width*0.2, height=label_height)

        total_height = len(self.base_structure_count) * (label_height + padding)
        # 关键：宽度一定要够容纳两个标签，否则右侧会被裁掉
        self.inner_frame_1.config(width=left_width, height=total_height)
        self.inner_frame_2.config(width=right_width, height=total_height)

    def show_structure_count_messages(self):
        height  = 25
        padding = 5
        width = 0.7
        structure_count_messages = {"json结构:":len(self.structure), "去重结构:":len(self.structure_count), "基础结构:":len(self.base_structure_count)}
        tk.Label(self.frame1_5_1, text="修改前:", anchor='center',
            bg="#09FF00").place(relx=0, y=0, relwidth=1, height=height)
        tk.Label(self.frame1_5_2, text="修改后:", anchor='center',
            bg="#FFFB25").place(relx=0, y=0, relwidth=1, height=height)
        my_frame = self.frame1_5_2 if self.flag else self.frame1_5_1
        for i,(name,num) in enumerate(structure_count_messages.items()):
            y = (i+1)*(height + padding)
            tk.Label(my_frame, text=name, anchor='w',
                bg="#91CF8F").place(relx=0, y=y, relwidth=width, height=height)
            tk.Label(my_frame, text=num, anchor='w',
                bg="#ADD8E6").place(relx=width, y=y, relwidth=1-width, height=height)
        
    def change_material(self):
        """
        将修改后的材质写入tmp_table
        查询修改后的材质对应的结构路径并写入tmp_table
        """
        try:
            right_combos = self.inner_frame_2.winfo_children()
            left_labels = self.inner_frame_1.winfo_children()
            left_labels = [item for i, item in enumerate(left_labels) if i % 2 == 0]
            
            for l_item, r_item in zip(left_labels, right_combos):
                curr_structure_full_name = l_item['text']
                curr_material_name = r_item.get()
                
                # 使用参数化查询防止SQL注入
                sql = """
                    UPDATE tmp_table 
                    SET changed_material = ?
                    WHERE structure_full_name = ?
                """
                self.cursor.execute(sql, (curr_material_name, curr_structure_full_name))
        
            self.conn.commit()
            
        except Exception as e:
            self.conn.rollback()
            logging.error(f"更新材料时出错: {str(e)}")
        
        try:
            sql = "SELECT variant_name,changed_material FROM tmp_table;"
            result=self.cursor.execute(sql).fetchall()
            for  i,(variant_name,changed_material) in enumerate(result):
                try:
                    sql = """
                        SELECT structure_path
                        FROM tmp_table
                        WHERE 
                            variant_name = ? AND changed_material = ?
                    """
                    result_old = self.cursor.execute(sql,(variant_name,changed_material)).fetchall()
                    result_old = [item["structure_path"] for item in result_old]
                    # 替换材料后 variant_name AND changed_material 存在重复值
                    # print("result_old: ",result_old)
                except Exception as e:
                    logging.error(f"tmp_table 没有 variant_name = {variant_name} 并且 changed_material = {changed_material}")
                    messagebox.showerror("SQL错误", f"tmp_table \n没有 variant_name = {variant_name} 并且 changed_material = {changed_material}")

                try:
                    sql = """
                        SELECT structure_path  
                        FROM total_view 
                        WHERE variant_name=? AND structure_material=?
                    """
                    result_new = self.cursor.execute(sql,(variant_name,changed_material)).fetchall()
                    result_new = [item["structure_path"] for item in result_new]
                    # print("result_new: ",result_new)
                    # 理论上结果只有一行
                    if result_new == [] :
                        result_new = result_old
                        logging.error(f"total_view 没有 variant_name = {variant_name} 并且 structure_material = {changed_material}")
                except Exception as e:
                    logging.error(f"total_view 没有 variant_name = {variant_name} 并且 structure_material = {changed_material}")
                    messagebox.showerror("SQL错误", f"total_view \n没有 variant_name = {variant_name} 并且 structure_material = {changed_material}\n该项不替换材料, 继续执行")


                try:
                    if len(result_new) != len(result_old):
                        result_new = result_new*len(result_old)
                    for j,(new_item,old_item) in enumerate(zip(result_new,result_old)):
                        sql = """
                            UPDATE tmp_table 
                            SET changed_path = ? 
                            WHERE structure_path = ?;
                        """
                        self.cursor.execute(sql,(new_item,old_item))
                    #logging.error(f"{result_old}不在self.jsondata中")
                except Exception as e :
                    #logging.error(f"self.jsondata中,建筑结构路径替换失败")
                    pass
            sql ="""
                SELECT structure_path, changed_path 
                FROM tmp_table;
            """
            result = self.cursor.execute(sql).fetchall()
            structure_path_s = [item["structure_path"] for item in result]
            changed_path_s = [item["changed_path"] for item in result]

            for s_item, c_item in zip(structure_path_s, changed_path_s):
                for entry in self.jsondata["entries"]:
                    if entry["structure"] == s_item:
                        entry["structure"] = c_item

            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            logging.error(f"替换材料出错: {str(e)}")
            logging.error(f"替换材料出错: variant_name = {variant_name} AND changed_material = {changed_material}")
        
    def save_to_template(self):
        """
        保存修改的内容到self.jsondata, self.content
        保存修改后的self.content 到本地文件, 文件名：{原文件名}_修改.txt
        """
        self.flag = 1 # 控制显示修改后
        template_name=self.template_name_text.get(1.0,tk.END).rstrip()
        template_name = self.jsondata["name"] if not template_name else template_name
        if self.jsondata["name"] != template_name:  # 已修改模板名称
            self.jsondata["name"] = template_name
        elif "修改" in self.jsondata["name"]:
            self.jsondata["name"] = template_name
        else:
            self.jsondata["name"] = self.jsondata["name"]+"_修改"

        self.change_material()
        self.content=json.dumps(self.jsondata,indent=2,ensure_ascii=False)
        filename = self.file_combobox.get()
        with open(filename.split(".")[0]+"_修改.txt", "w", encoding="utf-8") as f:
            f.write(self.content)
        self.json_to_structure()
        self.show_text()
        self.creat_tmp_db()
        self.count_structure()
        self.calculate_base_structure()
        self.show_base_structure()
        self.show_structure_count_messages()
        self.calculate_resources()
        self.show_resources()
        
    def copy_to_clipboard(self):
        """
        复制内容到剪切板
        """
        content = self.text_box.get(1.0,tk.END)
        root.clipboard_clear()
        root.clipboard_append(content)
        root.update()
        messagebox.showinfo("复制成功", "建筑模板已复制到剪贴板!")

    def show_tmp_table_data(self):
        self.cursor.execute("select * from tmp_table")
        # Get column names
        columns = [desc[0] for desc in self.cursor.description]
        # Print column names
        print(columns)
        # Print data rows
        for row in self.cursor.fetchall():
            print(list(row))

    def calculate_resources(self):
        pic_path = resource_path("./pic/")
        with os.scandir(pic_path) as entries:
            pics = [os.path.splitext(entry.name)[0] for entry in entries if entry.is_file()]
        if len(pics) == 0 :
            logging.error(f"{pic_path}: 下不存在资源图片")
            return
        self.resources = { i : 0 for i in pics }
        pattern  = "Cementing_Paste, Clay, Crystal, Element, Element_Shard, Fiber, Flint, Hide, Metal_Ingot, Polymer, Stone, Thatch, Wood"
        if len(self.resources) == len(pattern.split(',')):
            for key in self.base_structure_count.keys():
                sql = f"""
                    SELECT {pattern}
                    FROM need 
                    WHERE structure_full_name = ?
                """
                result = self.cursor.execute(sql,(key,)).fetchone()
                if result == None:
                    logging.error(f"{key} - Missing data: need.structure_full_name")

                for i,item in enumerate(self.resources.keys()):
                    self.resources[item] += int(result[i])*int(self.base_structure_count[key])

            for key in list(self.resources.keys()):
                if self.resources[key] == 0:
                    self.resources.pop(key)

            print(self.resources)
            logging.info({f"资源解析结果: {self.resources}"})
        else: 
            logging.error(f"资源字典的长度: {len(self.resources)}, need表的资源种类数: {len(pattern.split(','))}")
            messagebox.showerror('资源文件数量错误',f"资源字典的长度: {len(self.resources)} \nneed表的资源种类数: {len(pattern.split(','))}")
                
    def show_resources(self):
        for widget in self.inner_frame_3.winfo_children():
            widget.destroy()

        label_height2 = 25
        padding2 = 5
        width1 =  self.frame1_5_3.winfo_width()

        for i, (name, count) in enumerate(self.resources.items()):
            y = i * (label_height2 + padding2)
            picname="./pic/"+ name + ".png"
            ph1 = Image.open(resource_path(picname))
            ph1 = ph1.resize((round(label_height2),round(label_height2)))
            photo = ImageTk.PhotoImage(ph1)
            # 材料图片
            tmp1 = tk.Label(self.inner_frame_3, anchor="w", image=photo,
                    bg="#91CF8F")
            tmp1.image = photo
            tmp1.place(x=0, y=y, width=width1*0.5, height=label_height2)

            # 材料数量
            tk.Label(self.inner_frame_3, text=str(count), anchor="w",
                    bg="#ADD8E6").place(x=width1*0.5, y=y, width=width1*0.5, height=label_height2)
        total_height = len(self.resources) * (label_height2 + padding2)
        # 必须设置inner_frame的大小
        self.inner_frame_3.config(width=width1, height=total_height)





if __name__ == "__main__":
    root = tk.Tk()
    root.title("方舟飞升建筑模板辅助工具--DaringWoo@bilibili.com")
    root.iconbitmap(default=resource_path("./my_icon.ico"))
    root.resizable(False, False)
    root.geometry("900x600")
    app = App(root)
    root.mainloop()
